/*
 * Class.h
 *
 *  Created on: 2011-7-8
 *      Author: gexiao
 */
/*
 * Class loader
 */
#ifndef CLASS_H_
#define CLASS_H_

#include <stdbool.h>
/*
 * The classpath and bootclasspath differ in that only the latter is
 * consulted when looking for classes needed by the VM. When searching
 * for an arbitrary class definition, we start with the bootclasspath,
 * look for optional packages (a/k/a standard extensions), and then try
 * the classpath.
 *
 * In Dalvik, a class can be found in one of three ways:
 * 	- as a "loose".class file in a directory
 * 	- as a .class file held in a JAR archive
 * 	- in a .dex file
 *
 * These three may be freely intermixed in a classpath specification.
 * Ordering is significant. (Currently only ".dex" is supported directly
 * by the VM.)
 */
typedef struct ClassPathEntry {
	enum {
		kCpeUnknown = 0, kCpeDir, kCpeJar, kCpeDex, kCpeLastEntry
	} kind;
	char* filename;
	void* ptr; //JarFile* or DexFile*
} ClassPathEntry;

bool dvmClassStartup(void);

/*
 * Find the class with the given descriptor. Load it if it hasn't already
 * been.
 *
 * "loader" is the initiating class loader.
 */
ClassObject* dvmFindClassNoInit(const char* descriptor, Object* loader);

/*
 * Like dvmFindClass, but only for system classes.
 */
ClassObject* dvmFindSystemClass(const char* descriptor);
ClassObject* dvmFindSystemClassNoInit(const char* descriptor);

/*
 * Link a loaded class. Normally done as part of one of the "find class"
 * variations, this is only called explicitly for synthetic class
 * generation (e.g. reflect.Proxy).
 */
bool dvmLinkClass(ClassObject* clazz, bool classesResolved);

/*
 * Determine if a class has been initialized.
 */
INLINE bool dvmIsClassInitialized(const ClassObject* clazz) {
	return (clazz->status==CLASS_INITIALIZED);
}

/*
 * Initialize a class.
 */
bool dvmInitClass(ClassObject* clazz);

/*
 * Retrieve the system class loader.
 */
Object* dvmGetSystemClassLoader(void);

/*
 * Utility functions.
 */
ClassObject* dvmLookupClass(const char* descriptor, Object* loader,
		bool unprepOkey);
void dvmFreeClassInnards(ClassObject* clazz);
bool dvmAddClassToHash(ClassObject* clazz);

/*
 * Compute the number of argument words (u4 units) required by the
 * given method's prototype. For example, if the method descriptor is
 * "(IJ)D", this would return 3 (one for the int, two for the long;
 * return value isn't relevant).
 */
INLINE int dvmComputeMethodArgsSize(const Method* method) {
	return dexProtoComputeArgsSize(&method->prototype);
}

/*
 * Compare the two method prototypes. The two prototypes are compared
 * as if by strcmp() on the result of dexProtoGetMethodDescriptor().
 */
INLINE int dvmCompareMethodProtos(const Method* method1, const Method* method2) {
	return dexProtoCompare(&method1->prototype, &method2->prototype);
}

/*
 * Compare the two method names and prototypes, a la strcmp(). The
 * name is considered the "major" order and the prototype the "minor"
 * order. The prototypes are compared as if by dexProtoGetMethodDescriptor().
 */
int
dvmCompareMethodNamesAndProtos(const Method* method1, const Method* method2);

/*
 * Compare a method descriptor string with the prototype of a method,
 * as if by converting the descriptor to a DexProto and comparing it
 * with dexProtoCompare().
 */
INLINE int dvmCompareDescriptorAndMethodProto(const char* descriptor,
		const Method* method) {
	// Sense is reversed.
	return -dexProtoCompareToDescriptor(&method->prototype, descriptor);
}

/*
 * Compare a (name, method descriptor) pair with the (name, prototype) of
 * a method, a la strcmp(). The name is considered the "major" order and
 * the prototype the "minor" order. The descriptor and prototype are
 * compared as if by dvmCompareDescriptorAndMethodProto().
 */
int dvmCompareNameDescriptorAndMethod(const char* name, const char* descriptor,
		const Method* method);

#endif /* CLASS_H_ */
